package com.gaowl.gulimall.ware.service.impl;

import com.gaowl.common.constant.PurchaseStatusConstant;
import com.gaowl.gulimall.ware.dao.PurchaseDetailDao;
import com.gaowl.gulimall.ware.dao.WareSkuDao;
import com.gaowl.gulimall.ware.entity.PurchaseDetailEntity;
import com.gaowl.gulimall.ware.entity.WareSkuEntity;
import com.gaowl.gulimall.ware.service.PurchaseDetailService;
import com.gaowl.gulimall.ware.service.WareSkuService;
import com.gaowl.gulimall.ware.vo.MergeVo;
import com.gaowl.gulimall.ware.vo.PurchaseDoneVo;
import com.gaowl.gulimall.ware.vo.PurchaseDetailDoneVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gaowl.common.utils.PageUtils;
import com.gaowl.common.utils.Query;

import com.gaowl.gulimall.ware.dao.PurchaseDao;
import com.gaowl.gulimall.ware.entity.PurchaseEntity;
import com.gaowl.gulimall.ware.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {

    @Autowired
    PurchaseDetailDao purchaseDetailDao;

    @Autowired
    PurchaseDetailService purchaseDetailService;

    @Autowired
    WareSkuService wareSkuService;

    @Autowired
    WareSkuDao wareSkuDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );
        System.out.println(new PageUtils(page).toString());
        return new PageUtils(page);
    }


    /**
     * 查询未被领取的采购单（新建或已分配状态）
     */
    @Override
    public PageUtils queryUnreceivedBillList(Map<String, Object> params) {

        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>().eq("status", 0).or().eq("status", 1)
        );

        return new PageUtils(page);

    }

    /**
     * 合并采购需求
     * @param mergeVo 采购需求合并vo
     */
    @Transactional
    @Override
    public void mergePurchaseNeed(MergeVo mergeVo) {
        Long purchaseId = mergeVo.getPurchaseId();
        if (purchaseId == null){
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            purchaseEntity.setStatus(PurchaseStatusConstant.PurchaseStatusEnum.CREATED.getCode());   // 新建状态
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());
            this.save(purchaseEntity);

            purchaseId = purchaseEntity.getId();
        }

        // 开始合并，将wms_purchase_detail表中 id对应的记录 的purchase_id和status项
        List<Long> items = mergeVo.getItems();
        Long finalPurchaseId = purchaseId;

        List<PurchaseDetailEntity> purchaseDetailEntityList = items.stream().map(item -> {
            PurchaseDetailEntity purchaseDetailEntity = purchaseDetailDao.selectById(item);
            purchaseDetailEntity.setPurchaseId(finalPurchaseId);
            purchaseDetailEntity.setStatus(PurchaseStatusConstant.PurchaseStatusEnum.ASSIGNED.getCode());  // 已分配状态
            return purchaseDetailEntity;
        }).collect(Collectors.toList());
        purchaseDetailService.saveOrUpdateBatch(purchaseDetailEntityList);


        PurchaseEntity purchaseEntity = this.baseMapper.selectById(finalPurchaseId);
        purchaseEntity.setUpdateTime(new Date());
        this.updateById(purchaseEntity);
    }

    /**
     * 简化版指定某采购单已被领取
     * @param ids 采购单的id们
     */
    @Transactional
    @Override
    public void received(List<Long> ids) {
        ids.forEach(purchaseId ->{
            PurchaseEntity purchaseEntity = this.baseMapper.selectById(purchaseId);
            // 确认采购单的状态为新建或已分配
            if (purchaseEntity.getStatus() == PurchaseStatusConstant.PurchaseStatusEnum.CREATED.getCode() ||
                    purchaseEntity.getStatus() == PurchaseStatusConstant.PurchaseStatusEnum.ASSIGNED.getCode()){
                // 更新采购单的状态、更新时间
                purchaseEntity.setStatus(PurchaseStatusConstant.PurchaseStatusEnum.RECEIVED.getCode());
                purchaseEntity.setUpdateTime(new Date());
                this.baseMapper.updateById(purchaseEntity);

                // 更新采购单关联的采购需求们的状态为 正在采购
                List<PurchaseDetailEntity> detailEntities = purchaseDetailService.listDetailByPurchaseId(purchaseId);
                detailEntities = detailEntities.stream().map(purchaseDetailEntity -> {
                    purchaseDetailEntity.setStatus(PurchaseStatusConstant.PurchaseDetailStatusEnum.BUYING.getCode());
                    return purchaseDetailEntity;
                }).collect(Collectors.toList());
                purchaseDetailService.updateBatchById(detailEntities);
            }
        });
    }


    /**
     * 完成采用单
     * @param purchaseDoneVo 采购单完成情况
     */
    @Transactional
    @Override
    public void donePurchase(PurchaseDoneVo purchaseDoneVo) {

        Long purchaseId = purchaseDoneVo.getId();

        // ============= 找到此采购单关联的所有采购需求，并更新它们的完成情况 ===========
        List<PurchaseDetailEntity> purchaseDetailEntityList = purchaseDetailService.listDetailByPurchaseId(purchaseId);
        HashMap<Long, PurchaseDetailEntity> hashMap = new HashMap<>();
        for (PurchaseDetailEntity purchaseDetailEntity : purchaseDetailEntityList) {
            hashMap.put(purchaseDetailEntity.getId(), purchaseDetailEntity);   // 采购项id, 采购项具体情况
        }

        List<WareSkuEntity> updatedWareSkuEntityList = new ArrayList<>();

        List<PurchaseDetailDoneVo> items = purchaseDoneVo.getItems();
        for (PurchaseDetailDoneVo item : items) {
            Long itemId = item.getItemId();
            // 若某采购项未完成
            if (item.getStatus() == PurchaseStatusConstant.PurchaseDetailStatusEnum.EXCEPTION.getCode()){
                // 1.更新采购单状态
                PurchaseEntity purchaseEntity = this.baseMapper.selectById(purchaseId);
                purchaseEntity.setStatus(PurchaseStatusConstant.PurchaseStatusEnum.EXCEPTION.getCode());
                this.baseMapper.updateById(purchaseEntity);

                // 2.更新此采购项状态
                PurchaseDetailEntity purchaseDetailEntity = hashMap.get(itemId);
                purchaseDetailEntity.setStatus(PurchaseStatusConstant.PurchaseDetailStatusEnum.EXCEPTION.getCode());
                hashMap.put(itemId, purchaseDetailEntity);
            }else if (item.getStatus() == PurchaseStatusConstant.PurchaseDetailStatusEnum.FINISHED.getCode()){
                // 若物品成功完成采购
                PurchaseDetailEntity purchaseDetailEntity = hashMap.get(itemId);
                if (purchaseDetailEntity.getStatus() == PurchaseStatusConstant.PurchaseDetailStatusEnum.BUYING.getCode()){
                    // 1.更新采购项状态
                    purchaseDetailEntity.setStatus(PurchaseStatusConstant.PurchaseDetailStatusEnum.FINISHED.getCode());
                    hashMap.put(itemId, purchaseDetailEntity);

                    // 2.对采购完成的此物品，执行入库操作
                    Long skuId = purchaseDetailEntity.getSkuId();
                    Long wareId = purchaseDetailEntity.getWareId();
                    WareSkuEntity wareSkuEntity = wareSkuDao.selectOne(new QueryWrapper<WareSkuEntity>()
                            .eq("sku_id", skuId).eq("ware_id", wareId));
                    Integer skuNum = purchaseDetailEntity.getSkuNum();  // 需采购的数量
                    wareSkuEntity.setStock(wareSkuEntity.getStock() + skuNum);
                    updatedWareSkuEntityList.add(wareSkuEntity);
                }
            }
        }

        // 批量更新 数据库中采购项的状态 以减少数据库操作
        Collection<PurchaseDetailEntity> values = hashMap.values();
        if (values.size() > 0) {
            purchaseDetailService.updateBatchById(values);
        }

        if (updatedWareSkuEntityList.size() > 0){
            wareSkuService.updateBatchById(updatedWareSkuEntityList);
        }
    }
}